package top.mcwebsite.playandroid.business.user_article.impl.vm

import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import kotlinx.coroutines.launch
import top.mcwebsite.playandroid.business.articles.api.model.ArticleModel
import top.mcwebsite.playandroid.business.user_article.impl.netwrokapi.UserArticleApi
import top.mcwebsite.playandroid.common.network.ApiException
import top.mcwebsite.playandroid.common.network.BizApiException
import top.mcwebsite.playandroid.common.network.api.NetworkService
import top.mcwebsite.playandroid.common.network.api.createApi
import top.mcwebsite.playandroid.common.network.model.ApiResult
import top.mcwebsite.playandroid.common.user.api.IUserService
import top.mcwebsite.playandroid.lib.mvi.base.BaseViewModel
import top.mcwebsite.playandroid.lib.servicemanager.core.ServiceManager

class UserArticleViewModel : BaseViewModel<UserArticleIntent, UserArticleUIState, UserArticleUiEffect>(
    UserArticleUIState()
) {

    private val userArticleApi = ServiceManager.getService<NetworkService>().createApi<UserArticleApi>()

    private val pager = Pager(PagingConfig(pageSize = 10)) {
        UserArticlePageSource()
    }

    val pageFlow = pager.flow.cachedIn(viewModelScope)

    override fun handleIntent(intent: UserArticleIntent) {
        when (intent) {
            is UserArticleIntent.GoDetailPageIntent -> {
                sendUiEffect(UserArticleUiEffect.GoDetailPageUiEffect(intent.articleModel))
            }

            is UserArticleIntent.CollectionArticleIntent -> {
                collectionArticle(intent.articleModel)
            }

            is UserArticleIntent.UnCollectionArticleIntent -> {
                unCollectionArticle(intent.articleModel)
            }
        }
    }

    private fun collectionArticle(articleModel: ArticleModel) {
        // 先判断是否登录了，否则前往登录
        if (ServiceManager.getService<IUserService>().isLogin()) {
            collectionArticleWhenLogin(articleModel)
        } else {
            sendUiEffect(UserArticleUiEffect.GoLoginPageUiEffect)
        }
    }

    private fun unCollectionArticle(articleModel: ArticleModel) {
        if (ServiceManager.getService<IUserService>().isLogin()) {
            unCollectionArticleWhenLogin(articleModel)
        } else {
            // TODO
        }
    }

    private fun collectionArticleWhenLogin(articleModel: ArticleModel) {
        viewModelScope.launch {
            when (val result = userArticleApi.collectArticle(articleModel.id)) {
                is ApiResult.Success -> {
                    collectionSuccess(articleModel)
                }

                is ApiResult.Failure -> {
                    if (result.cause is BizApiException) {
                        if (result.cause.errorCode == BizApiException.UnLogin) {
                            sendUiEffect(UserArticleUiEffect.GoLoginPageUiEffect)
                        }
                    }
                }
            }
        }
    }

    private fun collectionSuccess(articleModel: ArticleModel) {
        setUiState {
            copy(
                collectionMap = uiState.collectionMap.toMutableMap().apply {
                    put(articleModel.id, true)
                }
            )
        }
    }

    private fun unCollectionArticleWhenLogin(articleModel: ArticleModel) {
        viewModelScope.launch {
            when (val result = userArticleApi.unCollectArticle(articleModel.id)) {
                is ApiResult.Success -> {
                    unCollectionSuccess(articleModel)
                }

                is ApiResult.Failure -> {

                }
            }
        }
    }

    private fun unCollectionSuccess(articleModel: ArticleModel) {
        setUiState {
            copy(
                collectionMap = uiState.collectionMap.toMutableMap().apply {
                    put(articleModel.id, false)
                }
            )
        }
    }

    fun isCollection(articleModel: ArticleModel): Boolean {
        return if (uiState.collectionMap.contains(articleModel.id)) {
            uiState.collectionMap[articleModel.id]!!
        } else {
            articleModel.collect
        }
    }

    fun refresh(action: () -> Unit) {
        setUiState {
            copy(refreshing = true)

        }
        action()
        setUiState {
            copy(refreshing = false, collectionMap = emptyMap())
        }
    }


    private inner class UserArticlePageSource : PagingSource<Int, ArticleModel>() {
        override fun getRefreshKey(state: PagingState<Int, ArticleModel>): Int? {
            return null
        }

        override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ArticleModel> {
            return try {
                val nextPageNumber = params.key ?: 0
                when (val apiResult = userArticleApi.userArticleList(nextPageNumber)) {
                    is ApiResult.Success -> {
                        LoadResult.Page(
                            data = apiResult.data.data?.datas ?: emptyList(),
                            prevKey = if (nextPageNumber == 0) null else nextPageNumber + 1,
                            nextKey = if (apiResult.data.data?.over == true) null else nextPageNumber + 1
                        )
                    }

                    is ApiResult.Failure -> {
                        LoadResult.Error(RuntimeException("未知错误"))
                    }
                }
            } catch (e: Exception) {
                return LoadResult.Error(e)
            }
        }

    }
}